﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ОписаниеПеременных

Перем СтарыеЗаписи, ГраницаСрокаНапоминания;

#КонецОбласти

#Область ОбработчикиСобытий

// АПК:75-выкл оповещение о напоминаниях должно быть при любом их изменении.
Процедура ПередЗаписью(Отказ, Замещение)
	
	Если Не БезОповещенияКлиента(ЭтотОбъект) Тогда
		ГраницаСрокаНапоминания = ТекущаяДатаСеанса()
			+ НапоминанияПользователяСлужебный.ЗапасВремениНапоминанийДляКэша();
		СтарыеЗаписи = СтарыеЗаписи(ЭтотОбъект, Отказ, Замещение);
	КонецЕсли;
	
	Если ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого Запись Из ЭтотОбъект Цикл
		Запись.ПредставлениеИсточника = ОбщегоНазначения.ПредметСтрокой(Запись.Источник);
		Если Запись.СпособУстановкиВремениНапоминания <> Перечисления.СпособыУстановкиВремениНапоминания.ОтносительноВремениПредмета Тогда
			Запись.ИмяРеквизитаИсточника = "";
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Процедура ПриЗаписи(Отказ, Замещение)
	
	Если Не БезОповещенияКлиента(ЭтотОбъект) Тогда
		ОтправитьОповещениеКлиенту(СтарыеЗаписи, ЭтотОбъект, Отказ, Замещение);
	КонецЕсли;
	
	Если ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
КонецПроцедуры
// АПК:75-вкл

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция БезОповещенияКлиента(ТекущийОбъект)
	
	Возврат ТекущийОбъект.ЗаписьИсторииДанных.ПредставленияПолейДополнительныхДанных.Получить("БезОповещенияКлиента") <> Неопределено
	    Или ТекущийОбъект.ДополнительныеСвойства.Свойство("БезОповещенияКлиента");

КонецФункции

Процедура ОтправитьОповещениеКлиенту(СтарыеЗаписи, НовыеЗаписи, Отказ, Замещение)
	
	Если Отказ
	 Или Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда
		Возврат;
	КонецЕсли;
	
	СписокПолей = "Пользователь, ВремяСобытия, Источник, СрокНапоминания, Описание";
	Если Замещение Тогда
		ИзмененныеЗаписи = ИзмененныеЗаписи(СтарыеЗаписи, НовыеЗаписи, СписокПолей);
	Иначе
		ИзмененныеЗаписи = ЭтотОбъект;
	КонецЕсли;
	
	НапоминанияПользователей = Новый Соответствие;
	Для Каждого Запись Из ИзмененныеЗаписи Цикл
		Если Запись.СрокНапоминания > ГраницаСрокаНапоминания Тогда
			Продолжить;
		КонецЕсли;
		Напоминания = НапоминанияПользователей.Получить(Запись.Пользователь);
		Если Напоминания = Неопределено Тогда
			Напоминания = НапоминанияПользователяСлужебный.НовыеИзмененныеНапоминания();
			НапоминанияПользователей.Вставить(Запись.Пользователь, Напоминания);
		КонецЕсли;
		Свойства = Новый Структура(СписокПолей);
		ЗаполнитьЗначенияСвойств(Свойства, Запись);
		Свойства.Вставить("ИндексКартинки", 2);
		Если Не Замещение Или Запись.ВидИзмененияСтроки = 1 Тогда
			Напоминания.Добавленные.Добавить(Свойства);
		Иначе
			Напоминания.Удаленные.Добавить(Свойства);
		КонецЕсли;
	КонецЦикла;
	
	ИмяОповещения = НапоминанияПользователяКлиентСервер.ИмяСерверногоОповещения();
	
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);
	
	Для Каждого КлючИЗначение Из НапоминанияПользователей Цикл
		ПользовательИБ = Пользователи.НайтиПоСсылке(КлючИЗначение.Ключ);
		Если ПользовательИБ = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Адресаты = Новый Соответствие;
		Адресаты.Вставить(ПользовательИБ.УникальныйИдентификатор,
			ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве("*"));
		СерверныеОповещения.ОтправитьСерверноеОповещение(ИмяОповещения,
			КлючИЗначение.Значение, Адресаты);
	КонецЦикла;
	
	УстановитьПривилегированныйРежим(Ложь);
	УстановитьОтключениеБезопасногоРежима(Ложь);
	
КонецПроцедуры

Функция СтарыеЗаписи(НаборЗаписей, Отказ, Замещение)
	
	Если Отказ
	 Или Не Замещение
	 Или Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Напоминания.Пользователь КАК Пользователь,
	|	Напоминания.ВремяСобытия КАК ВремяСобытия,
	|	Напоминания.Источник КАК Источник,
	|	Напоминания.СрокНапоминания КАК СрокНапоминания,
	|	Напоминания.Описание КАК Описание,
	|	-1 КАК ВидИзмененияСтроки
	|ИЗ
	|	РегистрСведений.НапоминанияПользователя КАК Напоминания
	|ГДЕ
	|	Напоминания.СрокНапоминания <= &ГраницаСрокаНапоминания
	|	И &УсловиеОтбора";
	
	Запрос.УстановитьПараметр("ГраницаСрокаНапоминания", ГраницаСрокаНапоминания);
	
	УсловиеОтбора = "ИСТИНА";
	Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
		Если Не ЭлементОтбора.Использование Тогда
			Продолжить;
		КонецЕсли;
		УсловиеОтбора = УсловиеОтбора + "
		|	И " + ЭлементОтбора.Имя + " = &" + ЭлементОтбора.Имя;
		Запрос.УстановитьПараметр(ЭлементОтбора.Имя, ЭлементОтбора.Значение);
	КонецЦикла;
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеОтбора", УсловиеОтбора);
	
	Возврат Запрос.Выполнить().Выгрузить();
	
КонецФункции

Функция ИзмененныеЗаписи(СтарыеЗаписи, НовыеЗаписи, СписокПолей)
	
	Для Каждого Запись Из НовыеЗаписи Цикл
		Если Запись.СрокНапоминания > ГраницаСрокаНапоминания Тогда
			Продолжить;
		КонецЕсли;
		НоваяСтрока = СтарыеЗаписи.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, Запись);
		НоваяСтрока.ВидИзмененияСтроки = 1;
	КонецЦикла;
	
	СтарыеЗаписи.Свернуть(СписокПолей, "ВидИзмененияСтроки");
	
	Строки = СтарыеЗаписи.НайтиСтроки(Новый Структура("ВидИзмененияСтроки", 0));
	Для Каждого Строка Из Строки Цикл
		СтарыеЗаписи.Удалить(Строка);
	КонецЦикла;
	
	Возврат СтарыеЗаписи;
	
КонецФункции

#КонецОбласти


#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли